package co.fitstart.mobile.web.controller.auth;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.support.Result;
import com.demo2do.core.web.handler.CookieHandler;
import com.demo2do.core.web.utils.WebUtils;
import com.demo2do.core.wechat.authorization.AuthorizationScope;
import com.demo2do.core.wechat.authorization.handler.AppAuthHandler;
import com.demo2do.core.wechat.support.AppType;

import co.fitstart.mobile.Constant;

/**
 * 
 * @author mohanlan
 *
 */
@Controller
@RequestMapping("")
public class WechatBaseAuthController {
    
    private static final Logger logger = LoggerFactory.getLogger(WechatBaseAuthController.class);
    
    private static final String SAVED_REQUEST = "WECHAT_WEB_BASE_AUTH_SAVED_REQUEST";
    
    @Autowired
    private CookieHandler cookieHandler;
    
    @Autowired
    private AppAuthHandler appAuthHandler;
    
    /**
     * Prepare WeChat user info scoped authorization code URL and redirect to it
     * 
     * @param httpServletRequest
     * @return
     */
    @RequestMapping("/wx/pre-base-auth")
    public String preAuthorization(HttpServletRequest httpServletRequest) {
        String serverRealPath = WebUtils.getRealServerPath(httpServletRequest);
        String codeUrl = appAuthHandler.generateCodeUrl(serverRealPath + "/wx/post-base-auth", AuthorizationScope.BASE, AppType.OFFICIAL, null);
        
        logger.info("WechatBaseAuthController#preAuthorization the code url is [{}]", codeUrl);
        return "redirect:" + codeUrl;
    }
    
    /**
     * Receive code from WeChat user info scoped authorization and exchange
     * openid, access token with code
     * 
     * @param code
     * @param state
     * @param httpServletResponse
     * @param httpSession
     * @return
     */
    @RequestMapping("/wx/post-base-auth")
    public ModelAndView onPostAuthorization(@RequestParam(value = "code", required = false) String code,
                                            @RequestParam(value = "state", required = false) String state,
                                            HttpServletResponse httpServletResponse,
                                            HttpSession httpSession) {
        
        ModelAndView modelAndView = new ModelAndView();
        
        // Gets saved request from http session
        String originalUrl = (String) httpSession.getAttribute(SAVED_REQUEST);
        
        // If code returned from wechat is not empty, then goes to retrieve openid using code
        if (StringUtils.isNotBlank(code)) {
            
            // get access token first
            Result authResult = appAuthHandler.exchangeAccessToken(code, AppType.OFFICIAL);
            
            if (authResult.isValid()) {
                
                // Extract openid, access token and expires time
                String openid = (String) authResult.get("openid");
                int expireTime = ((Integer) authResult.get("expires_in")).intValue();
                
                cookieHandler.addCookie(httpServletResponse, Constant.OPENID_KEY, openid, expireTime);
                
                // If original URL is not empty, redirect to original URL. Or redirect to root path.
                if (StringUtils.isNotBlank(originalUrl)) {
                    modelAndView.setViewName("redirect:" + originalUrl);
                } else {
                    modelAndView.setViewName("redirect:/");
                }
                
            } else {
                
                modelAndView.setViewName("auth-error");
                modelAndView.addObject("errmsg", authResult.get("errmsg"));
            
            }
            
        } else {
            
            logger.error("WechatAuthorizationController#onPostAuthorization() - Requesting WeChat code occurs unknown errors. No code returned from WeChat.");
        }
        
        return modelAndView;
    }
}
